package com.hzeng.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;


public class CSVUtil {
	
	public static String[] readHeader(File filePath) {
		CSVReader reader = null;
		if (filePath == null) {
			return null;
		}
		if (filePath.exists() && filePath.isFile()) {
			
			String[] nextLine = null;
			
			try {
				reader = new CSVReader(new FileReader(filePath));
				while ((nextLine = reader.readNext()) != null) {
					if (nextLine.length > 1) {
						if (nextLine[0].startsWith("#")) {
							continue;
						}else if (nextLine[0].equals(Constants._TIME)) {
							return nextLine;
						}
					}else {
						continue;
					}
					
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					reader.close();
				} catch (Exception e2) {
					e2.printStackTrace();
				}
			}
			return null;
		}else {
			return null;
		}
	}
	
	public static String[] readSchema(File filePath) {
		CSVReader reader = readFile(filePath);
		if (reader == null) {
			return null;
		}else {
			return readSchema(reader);
		}
	}
	
	public static CSVReader readFile(File filePath) {
		CSVReader reader = null;
		if (filePath == null) {
			return null;
		}
		if (filePath.exists() && filePath.isFile()) {
			try {
				reader = new CSVReader(new FileReader(filePath));
				return reader;
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}else {
			return null;
		}
	}
	
	
	public static String[] readSchema(CSVReader reader) {
		String[] nextLine = null;
		try {
			while ((nextLine = reader.readNext()) != null) {
				if (nextLine.length > 1) {
					if (nextLine[0].startsWith("#")) {
						return nextLine;
						
					}else if (nextLine[0].equals(Constants._TIME)) {
						continue;
					}else{
						continue;
					}
				}else {
					continue;
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	public static String[] readRowData(CSVReader reader) {
		String[] nextLine = null;
		try {
			while ((nextLine = reader.readNext()) != null) {
				if (nextLine.length > 1) {
					if (nextLine[0].startsWith("#")) {
						continue;
					}else if (nextLine[0].equals(Constants._TIME)) {
						continue;
					}else{
						return nextLine;
					}
				}else {
					continue;
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static CSVReader readSchema(CSVReader reader,String[] schema) {
		try {
			while ((schema = reader.readNext()) != null) {
				if (schema.length > 1) {
					if (schema[0].startsWith("#")) {
						return reader;
						
					}else if (schema[0].equals(Constants._TIME)) {
						continue;
					}else{
						continue;
					}
				}else {
					continue;
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return reader;
	}
	
	public static CSVReader readRowData(CSVReader reader,String[] rowData) {
		try {
			while ((rowData = reader.readNext()) != null) {
				if (rowData.length > 1) {
					if (rowData[0].startsWith("#")) {
						continue;
					}else if (rowData[0].equals(Constants._TIME)) {
						continue;
					}else{
						return reader;
					}
				}else {
					continue;
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return reader;
	}
	
	public static CSVWriter createSysCSVFiles(File directoryPath,String name) {
		CSVWriter writer = null;
		if(directoryPath.exists() && directoryPath.isDirectory()) {
			File subFile = new File(directoryPath.getAbsoluteFile() + "/PM_0_" + name + ".csv");
			if (subFile.exists()) {
				
			}else {
				try {
					subFile.createNewFile();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			try {
				writer = new CSVWriter(new FileWriter(subFile,true), ',');
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return writer;
	}
	
	public static Map<Long,CSVWriter> createCSVFiles(File directoryPath,List<Program> programs) {
		Map<Long,CSVWriter> writers = new HashMap<Long, CSVWriter>();
		
		//writers.add(createSysCSVFiles(directoryPath,"system"));
		
		if(directoryPath.exists() && directoryPath.isDirectory()) {
			for (int i = programs.size() - 1; i >= 0; i--) {
				Program p = programs.get(i);
				if (p == null) {
					continue;
				}
				File subFile = null;
				if (p.getPid() == 0) {
					subFile = new File(directoryPath.getAbsoluteFile() + "/PM_" + Constants._SYS_NAME + ".csv");
				}else {
					subFile = new File(directoryPath.getAbsoluteFile() + "/PM_" + p.getPid() + ".csv");
				}
				CSVWriter writer = null;
				if (subFile.exists()) {
					try {
						writer = new CSVWriter(new FileWriter(subFile,true), ',');
					} catch (IOException e) {
						e.printStackTrace();
					}
				}else {
					try {
						subFile.createNewFile();
						String[] schema = ProgramMonitor.getInstance().recordProgramsSchema(p);
						String[] header = ProgramMonitor.getInstance().recordProgramHeader(p);
						try {
							writer = new CSVWriter(new FileWriter(subFile,true), ',');
							writer.writeNext(schema);
							writer.writeNext(header);
							writer.flush();
						} catch (IOException e) {
							e.printStackTrace();
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				writers.put(p.getPid(), writer);
			}
		}
		
		return writers;
	}
	
	
	public static List<CSVWriter> createCSVFile(File filePath,List<String[]> headers) {
		List<CSVWriter> writers = new ArrayList<CSVWriter>();
		
		if(filePath.exists()) {
			
		}else {
			try {
				filePath.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		try {
			for (int i = 0; i < headers.size(); i++) {
				CSVWriter writer = null;
				writer = new CSVWriter(new FileWriter(filePath,true), ',');
				writer.writeNext(headers.get(i));
				writer.flush();
				writers.add(writer);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return writers;
		
	}
	
	public static CSVWriter createCSVFile(File filePath,String[] header) {
		CSVWriter writer = null;
		if(filePath.exists()) {
			
		}else {
			try {
				filePath.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		try {
			writer = new CSVWriter(new FileWriter(filePath,true), ',');
			writer.writeNext(header);
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return writer;
		
	}
	
	public static void closeReaders(List<CSVReader> readers) {
		for (int i = 0; i < readers.size(); i++) {
			try {
				readers.get(i).close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	public static void closeWriters(Map<Long,CSVWriter> writers) {
		Iterator iter = writers.entrySet().iterator(); 
		while (iter.hasNext()) { 
		    Map.Entry entry = (Map.Entry) iter.next(); 
		    CSVWriter writer = (CSVWriter) entry.getValue(); 
		    if (writer != null) {
		    	try {
			    	writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				writer = null;
			}
		} 
	}
	
	public static void closeWriters(List<CSVWriter> writers) {
		for (int i = 0; i < writers.size(); i++) {
			try {
				writers.get(i).close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static Map<Long,CSVWriter> appendData(Map<Long,CSVWriter> writers,List<Program> programs) {
		if (programs == null || programs.size() < 1) {
			return writers;
		}
		
		for (int i = programs.size() - 1; i >= 0; i--) {
			Program p = programs.get(i);
			CSVWriter writer = writers.get(p.getPid());
			if (writer == null) {
				continue;
			}
			String[] programRow = null;
			if (p.getPid() == 0) {
				programRow = new String[8];
				programRow[0] = p.getTimestamp() + "";
				programRow[1] = p.getCpu() + "";
				programRow[2] = p.getVirtualMemory() + "";
		    	programRow[3] = p.getMemory() + "";
				programRow[4] = p.getRead() + "";
		        programRow[5] = p.getWrite() + "";
				programRow[6] = p.getReadBytes() + "";
	            programRow[7] = p.getWriteBytes() + "";
			}else {
				programRow = new String[4];
				programRow[0] = p.getTimestamp() + "";
				programRow[1] = p.getCpu() + "";
				programRow[2] = p.getVirtualMemory() + "";
		    	programRow[3] = p.getMemory() + "";
			}
			try {
				writer.writeNext(programRow);
	            writer.flush();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return writers;
	}
	
	
	public static CSVWriter appendData(CSVWriter writer,String[] rowData) {
		try {
			writer.writeNext(rowData);
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return writer;
	}
	
	public static void createCSV(File filePath,String[] rowData) {
		CSVWriter writer = null;
		CSVReader reader = null;
		
		if(filePath.exists()) {
			
		}else {
			try {
				filePath.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
		String[] nextLine;
		int rowNum = 0;
		boolean hasHead = false;
		String[] rowLabel = null;
		try {
			reader = new CSVReader(new FileReader(filePath));
			while ((nextLine = reader.readNext()) != null) {
				rowNum++;
				if(rowNum == 1) {
					rowLabel = nextLine;
					//add code here
					int columnNum = 0;
					for (int i = 0; i < nextLine.length; i++) {
						try {
							new Double(nextLine[i]);
						} catch (Exception e) {
							
							columnNum++;
							
						}
					}
					if(columnNum == nextLine.length){
						hasHead = true;
						break;
					}else {
						return;
					}
				}else{
					break;
				}
			}
			reader.close();
			
			
			writer = new CSVWriter(new FileWriter(filePath,true), ',');
			
			if(hasHead) {
				
			}else {
				//create head
				writer.writeNext(rowLabel);
			}
			writer.writeNext(rowData);
			writer.flush();
			writer.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
